# -*- coding: utf-8 -*-
import logging.config
from PyQt5.QtCore import QThread, pyqtSignal, QSettings
from socket import *
import re
import os
import socket
import time
import pyaudio
import numpy as np
import wave
import traceback
import json
from util.Tools import recvoicedemo
from util.sdk.TXTool import requestExample
from util.sdk.TXrealtime import sendVoice

setting = QSettings(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config\\config.ini"),
                    QSettings.IniFormat)
setting.setIniCodec("UTF-8")
logging.config.fileConfig(
    os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config\\logging.ini"))
logging.getLogger("infoLogger")
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
WAVE_OUTPUT_FILENAME = "output.wav"
LangTime = 2
Leven = int(setting.value("SpeechRecognition/Leven"))
Threshold = int(setting.value("SpeechRecognition/Threshold"))


class Server_RunThread(QThread):
    tcp_action_signal = pyqtSignal(dict)
    tcp_status_feedback = pyqtSignal(str)
    tcp_status_freetimestatus = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        p = pyaudio.PyAudio()

        self.stream = p.open(format=FORMAT,
                             channels=CHANNELS,
                             rate=RATE,
                             input=True,
                             frames_per_buffer=CHUNK)
        self.Client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.Client.settimeout(5)
        self.tapeing = True
        self.recordstatus = 0
        self.startNum = 0

    def savewav(self, filename):
        try:
            wf = wave.open(filename, 'wb')
            wf.setnchannels(CHANNELS)
            wf.setsampwidth(2)
            wf.setframerate(RATE)
            # wf.writeframes(np.array(self.frames).tostring())
            wf.writeframes(b''.join(self.frames))
            wf.close()
        except Exception:
            logging.error(traceback.format_exc())

    # def run(self):
    #     try:
    #         baseFile = os.path.dirname(os.path.abspath(__file__))
    #         FileName = os.path.join(baseFile,"input.wav")
    #
    #         while self.tapeing:
    #             logging.info("开始录音")
    #             recvoicedemo(FileName)
    #             # ret = requestExample(FileName)
    #             logging.error("结束录音")
    #             ret = sendVoice(FileName,True)
    #
    #             obj = json.loads(ret)
    #             item = obj["text"]
    #             logging.info(item)
    #             # if item=="结束录音"in item and self.recordstatus==1:
    #             if re.search(r'\d*结束录音\d*', item) != None and self.recordstatus == 1:
    #                 self.recordstatus = 0
    #                 self.startNum = 0
    #                 InsturcDict = {}
    #                 InsturcDict["AsrComent"] = "录音功能关闭，"
    #                 InsturcDict["InstrucId"] = 1
    #                 InsturcDict["Success"] = False
    #                 self.tcp_action_signal.emit(InsturcDict)
    #             if self.recordstatus ==1 and self.startNum==1:
    #                 if len(item)>0:
    #                     InsturcDict={}
    #                     InsturcDict["AsrComent"] = item
    #                     InsturcDict["InstrucId"] = 1
    #                     InsturcDict["Success"] = True
    #                     self.tapeing = False
    #                     self.tcp_action_signal.emit(InsturcDict)
    #                 else:
    #                     self.tapeing = True
    #                     # InsturcDict = {}
    #                     # InsturcDict["AsrComent"] = "语音识别失败！请再来一次"
    #                     # InsturcDict["InstrucId"] = 1
    #                     # InsturcDict["Success"] = False
    #                     # self.tcp_action_signal.emit(InsturcDict)
    #             # if item=="开始录音"in item and self.startNum==0:
    #             if re.search(r'\d*开始录音\d*',item)!=None and self.startNum==0:
    #                 self.recordstatus = 1
    #                 self.startNum=1
    #                 InsturcDict = {}
    #                 InsturcDict["AsrComent"] = "录音功能开启，"
    #                 InsturcDict["InstrucId"] = 1
    #                 InsturcDict["Success"] = False
    #                 self.tcp_action_signal.emit(InsturcDict)
    #             # self.waveshardsend(self.Client, RecordDate)
    #     except Exception:
    #         logging.error(traceback.format_exc())
    def run(self):
        try:
            while self.tapeing:
                print("开始录音")
                self.status = 0  # 未开始
                self.frames = []
                # self.Client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                # self.Client.connect(
                #     (setting.value("SpeechRecognition/ip"), int(setting.value("SpeechRecognition/port"))))
                while True:

                    data = self.stream.read(CHUNK)  # 需要检测的数据
                    ret = self.reduceGetVoiceByte(data)
                    if ret:
                        self.tcp_status_feedback.emit("录音中。。。。")
                        self.status = 1
                        self.frames.append(data)
                        if hasattr(self, "QtimeGo"):
                            # 无音检测
                            delattr(self, "QtimeGo")
                    if ret == None and self.status == 1:  # 该段无音
                        # 清楚录音中的状态？
                        if hasattr(self, "QtimeGo"):
                            EndTime = time.time()
                            if (EndTime - self.QtimeGo) >= LangTime:
                                self.status = 0
                                del self.QtimeGo
                                break
                            else:
                                self.frames.append(data)
                                continue
                        else:
                            self.QtimeGo = time.time()
                logging.info("音频检测")
                if len(self.frames) > 3:  # 采集个音频个数
                    # RecordDate = b''.join(self.frames)
                    BasePath = os.path.dirname(os.path.abspath(__file__))
                    FileName = os.path.join(BasePath, "input.wav")
                    self.savewav(FileName)
                    self.tcp_status_feedback.emit("语音识别中。。。。")
                    item = requestExample(FileName)

                    if len(item) > 0:
                        # Nip()
                        InsturcDict = {}
                        InsturcDict["AsrComent"] = item
                        InsturcDict["InstrucId"] = 1
                        InsturcDict["Success"] = True
                        self.tapeing = False
                        self.tcp_action_signal.emit(InsturcDict)
                    else:
                        self.tapeing = False
                        InsturcDict = {}
                        InsturcDict["AsrComent"] = "未识别到声音！请再次输入语音"
                        InsturcDict["InstrucId"] = 1
                        InsturcDict["Success"] = False
                        self.tcp_action_signal.emit(InsturcDict)
                else:
                    self.frames = []
                    self.tcp_status_freetimestatus.emit("over")
        except Exception:
            logging.error(traceback.format_exc())
            print("走到这里了")
            self.tapeing = True

    def waveshardsend(self, Client, RecordDate):
        '''
        分片发送
        :param Client:
        :return:
        '''
        try:
            print(len(RecordDate))
            Client.send(len(RecordDate).to_bytes(2, "little"))
            Client.settimeout(30)
            Client.send(RecordDate)
            print("发送结束")
            ret = Client.recv(1024).decode("utf-8")
            logging.info("等待回信")
            itemObj = json.loads(ret)
            if itemObj["Success"]:
                self.tapeing = False
                Client.close()
                self.tcp_action_signal.emit(itemObj)
            else:
                self.tapeing = True
                Client.close()
        except Exception:
            self.tapeing = True
            logging.error(traceback.format_exc())

    def reduceGetVoiceByte(self, voice):
        '''
        分析音频数据
        :param voice: 5秒内的语音BYTE数据
        :return ret: 可保存的音频数据
        :return status: 运行状态[录音中，录音结束，不需要录音(无效音频数据)]
        '''

        try:
            VoiceByteDate = np.fromstring(voice, dtype=np.short)
            NumBer = np.sum(VoiceByteDate > Threshold)  # 大于阈值的个数
            print(NumBer)
            if NumBer > Leven:
                ret = 1
            else:
                ret = None
            return ret
        except Exception:
            logging.error(traceback.format_exc())
